/*
 * Copyright (C) 2015 Daniel Uppenkamp
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.googlecode.maurersmarbles;

import com.google.common.base.Preconditions;

/**
 *
 * @author Daniel Uppenkamp
 */
public class Card {

    /**
     * A standard playing card is 2.5" x 3.5".
     */
    public static final float WIDTH_TO_HEIGHT_RATIO = 2.5f / 3.5f;
    /**
     * The card id for a split card.
     */
    public static final int CARD_ID_SPLIT = 0;
    /**
     * The card id for the Ace.
     */
    public static final int CARD_ID_A = 1;
    /**
     * The card id for the 2.
     */
    public static final int CARD_ID_2 = 2;
    /**
     * The card id for the 3.
     */
    public static final int CARD_ID_3 = 3;
    /**
     * The card id for the 4.
     */
    public static final int CARD_ID_4 = 4;
    /**
     * The card id for the 5.
     */
    public static final int CARD_ID_5 = 5;
    /**
     * The card id for the 6.
     */
    public static final int CARD_ID_6 = 6;
    /**
     * The card id for the 7.
     */
    public static final int CARD_ID_7 = 7;
    /**
     * The card id for the 8.
     */
    public static final int CARD_ID_8 = 8;
    /**
     * The card id for the 9.
     */
    public static final int CARD_ID_9 = 9;
    /**
     * The card id for the 10.
     */
    public static final int CARD_ID_10 = 10;
    /**
     * The card id for the Jack.
     */
    public static final int CARD_ID_J = 11;
    /**
     * The card id for the Queen.
     */
    public static final int CARD_ID_Q = 12;
    /**
     * The card id for the King.
     */
    public static final int CARD_ID_K = 13;
    /**
     * The array that contains the card ids.
     */
    public static final int[] CARD_IDS = {CARD_ID_A, CARD_ID_2, CARD_ID_3,
        CARD_ID_4, CARD_ID_5, CARD_ID_6, CARD_ID_7, CARD_ID_8, CARD_ID_9,
        CARD_ID_10, CARD_ID_J, CARD_ID_Q, CARD_ID_K};
    /**
     * The card suit for the clubs.
     */
    public static final char CARD_SUIT_CLUBS = 'C';
    /**
     * The card suit for the diamonds.
     */
    public static final char CARD_SUIT_DIAMONDS = 'D';
    /**
     * The card suit for the hearts.
     */
    public static final char CARD_SUIT_HEARTS = 'H';
    /**
     * The card suit for the spades.
     */
    public static final char CARD_SUIT_SPADES = 'S';
    /**
     * The array that contains the card suits.
     */
    public static final char[] CARD_SUITS = {CARD_SUIT_CLUBS,
        CARD_SUIT_DIAMONDS, CARD_SUIT_HEARTS, CARD_SUIT_SPADES};
    /**
     * The card text for a split card.
     */
    private static final String CARD_TEXT_SPLIT = "S";
    /**
     * The card text for the Ace.
     */
    private static final String CARD_TEXT_A = "A";
    /**
     * The card text for the 2.
     */
    private static final String CARD_TEXT_2 = "2";
    /**
     * The card text for the 3.
     */
    private static final String CARD_TEXT_3 = "3";
    /**
     * The card text for the 4.
     */
    private static final String CARD_TEXT_4 = "4";
    /**
     * The card text for the 5.
     */
    private static final String CARD_TEXT_5 = "5";
    /**
     * The card text for the 6.
     */
    private static final String CARD_TEXT_6 = "6";
    /**
     * The card text for the 7.
     */
    private static final String CARD_TEXT_7 = "7";
    /**
     * The card text for the 8.
     */
    private static final String CARD_TEXT_8 = "8";
    /**
     * The card text for the 9.
     */
    private static final String CARD_TEXT_9 = "9";
    /**
     * The card text for the 10.
     */
    private static final String CARD_TEXT_10 = "10";
    /**
     * The card text for the Jack.
     */
    private static final String CARD_TEXT_J = "J";
    /**
     * The card text for the Queen.
     */
    private static final String CARD_TEXT_Q = "Q";
    /**
     * The card text for the King.
     */
    private static final String CARD_TEXT_K = "K";
    /**
     * The array that contains the card display texts.
     */
    private static final String[] CARD_TEXTS = {CARD_TEXT_SPLIT, CARD_TEXT_A,
        CARD_TEXT_2, CARD_TEXT_3, CARD_TEXT_4, CARD_TEXT_5, CARD_TEXT_6,
        CARD_TEXT_7, CARD_TEXT_8, CARD_TEXT_9, CARD_TEXT_10, CARD_TEXT_J,
        CARD_TEXT_Q, CARD_TEXT_K,};
    /**
     * The card suit.
     */
    private char suit;
    /**
     * The card id.
     */
    private int id;
    /**
     * The card value.
     */
    private int value;
    /**
     * The card text.
     */
    private String text;

    /**
     * Creates a new Card.
     *
     * @param id the card id
     * @param suit the card suit
     */
    public Card(int id, char suit) {
        this(id, suit, id);
    }

    /**
     * Creates a new Card.
     *
     * @param id the card id
     * @param suit the card suit
     * @param value the card value
     */
    public Card(int id, char suit, int value) {

        Preconditions.checkArgument(id >= 0 && id < CARD_TEXTS.length, "Invalid card id");

        this.id = id;
        this.suit = suit;
        this.value = value;
        text = CARD_TEXTS[id];

    }

    /**
     * Creates a new Card.
     *
     * @param card the card to copy
     */
    public Card(Card card) {

        Preconditions.checkNotNull(card, "Null card");

        this.id = card.id;
        this.suit = card.suit;
        this.value = card.value;
        this.text = card.text;

    }

    /**
     * Returns the card id.
     *
     * @return the card id
     */
    public int getId() {
        return id;
    }

    /**
     * Returns the suit for this card.
     *
     * @return the suit for this card
     */
    public char getSuit() {
        return suit;
    }

    /**
     * Returns the card text.
     *
     * @return the card text
     */
    public String getText() {
        return text;
    }

    /**
     * Returns the card value.
     *
     * @return the card value
     */
    public int getValue() {
        return value;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        result = prime * result + suit;
        result = prime * result + ((text == null) ? 0 : text.hashCode());
        result = prime * result + value;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        Card other = (Card) obj;
        if (id != other.id) {
            return false;
        }
        if (suit != other.suit) {
            return false;
        }
        if (text == null) {
            if (other.text != null) {
                return false;
            }
        }
        else if (!text.equals(other.text)) {
            return false;
        }
        if (value != other.value) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return text + suit;
//        StringBuilder stringBuilder = new StringBuilder();
//        stringBuilder.append(text).append(suit);
//        stringBuilder.append(", id=").append(id).append(", ");
//        stringBuilder.append("value=").append(value);
//        return stringBuilder.toString();
    }

}
